package gocache

import (
	"sync"
	"sync/atomic"
	"time"
)

type cacheValue struct {
	val any
	dna int32
}

type MapCache struct {
	lk  sync.RWMutex
	lst map[string]*cacheValue
}

func NewMapCache() CacheOperator {
	return &MapCache{lst: make(map[string]*cacheValue)}
}

var (
	valDNA atomic.Int32
)

func (this *MapCache) SetWithTTL(k string, v any, ttl time.Duration) {
	dna := valDNA.Add(1)
	this.lk.Lock()
	defer this.lk.Unlock()
	val, ok := this.lst[k]
	if !ok {
		val = &cacheValue{val: v, dna: dna}
		this.lst[k] = val
	} else {
		val.val = v
		val.dna = dna
	}
	if ttl > 0 {
		time.AfterFunc(ttl, func() {
			if val.dna == dna {
				this.lk.Lock()
				defer this.lk.Unlock()
				if val.dna == dna {
					delete(this.lst, k)
				}
			}

		})
	}

}

func (this *MapCache) Del(k string) {
	this.lk.Lock()
	defer this.lk.Unlock()
	delete(this.lst, k)
}

func (this *MapCache) Get(k string) (v any, ok bool) {
	this.lk.RLock()
	defer this.lk.RUnlock()
	v0, ok0 := this.lst[k]
	if ok0 {
		return v0.val, true
	}
	return nil, false
}

func (this *MapCache) Wait() {

}
